<template>
  <div
    v-if="authentication && inited"
    class="login-view"
    :class="`${currentThemeId}-login-theme`"
  >
    <Swiper
      v-if="['lb', 'gs'].includes(currentThemeId)"
      :items="swiperList"
    />
    <div :class="['lb', 'gs'].includes(currentThemeId) ? 'full-box' : 'min-height-box'">
      <div :class="['lb', 'gs'].includes(currentThemeId) ? 'full-box' : 'min-height-auto'">
        <div
          class="center-bj"
          v-if="currentThemeId !== 'gs'"
        >
          <el-image :src="currentTheme.THEME_AUX" />
        </div>
        <div
          class="center-logo"
          v-if="currentThemeId !== 'gs'"
        >
          <el-image :src="currentTheme.THEME_LOGO" />
        </div>
        <div class="login-main-content">
          <div
            class="center-logo"
            v-if="currentThemeId === 'gs'"
          >
            <el-image :src="currentTheme.THEME_LOGO" />
          </div>
          <div
            v-if="canChangeSignWay"
            class="toggle-sign-way"
            @click="usePassword=!usePassword"
          >
            <el-tooltip
              effect="light"
              :content="usePassword ? '扫码登录' : passwordTitle"
              placement="left"
            >
              <div
                class="toggle-button"
                :class="usePassword ? 'password': ''"
              />
            </el-tooltip>
            <!-- <div class="toggle-tips">微信登录在这里</div> -->
          </div>
          <div v-if="usePassword">
            <div class="title-area">
              {{ useSms ? smsTitle : passwordTitle }}
            </div>
            <el-form
              ref="form"
              :model="form"
              :rules="rules"
              class="login-form"
              label-position="left"
            >
              <template v-if="useSms">
                <el-form-item prop="mobile">
                  <BKInput
                    is-number
                    autofocus
                    v-model.trim="form.mobile"
                    placeholder="请输入手机号码"
                    tabindex="1"
                    prefix-icon="el-icon-mobile"
                  />
                </el-form-item>
                <el-form-item prop="smsCode">
                  <div class="d-flex ai-c">
                    <BKInput
                      placeholder="请输入验证码"
                      tabindex="2"
                      v-model.trim="form.smsCode"
                      prefix-icon="el-icon-chat-dot-round"
                    />
                    <el-button
                      class="yzm-button"
                      type="primary"
                      :disabled="sendCodeButtonDisabled"
                      @click="sendSms"
                    >
                      {{ sendCodeButtonText }}
                    </el-button>
                  </div>
                </el-form-item>
              </template>
              <template v-else>
                <el-form-item prop="username">
                  <el-input
                    autofocus
                    v-model.trim="form.username"
                    placeholder="请输入用户名"
                    tabindex="1"
                    type="text"
                    prefix-icon="el-icon-user"
                  />
                </el-form-item>
                <el-form-item prop="password">
                  <el-input
                    ref="password"
                    v-model.trim="form.password"
                    placeholder="请输入密码"
                    tabindex="2"
                    :type="passwordType"
                    prefix-icon="el-icon-unlock"
                  />
                  <span
                    v-if="canChangePasswordType"
                    class="show-pwd"
                    @click="togglePasswordType"
                  >
                    <i
                      :class="passwordType === 'password' ? 'ri-eye-off-line' : 'ri-eye-line'"
                    />
                  </span>
                </el-form-item>
                <el-form-item
                  prop="bifactorCode"
                  v-if="bifactorType"
                >
                  <div class="d-flex ai-c">
                    <BKInput
                      placeholder="请输入验证码"
                      tabindex="2"
                      v-model.trim="form.bifactorCode"
                      prefix-icon="el-icon-chat-dot-round"
                    />
                    <el-button
                      class="yzm-button"
                      type="primary"
                      :disabled="sendCodeButtonDisabled"
                      @click="getBifactorCode"
                    >
                      {{ sendCodeButtonText }}
                    </el-button>
                  </div>
                </el-form-item>
                <el-form-item
                  prop="code"
                  v-if="verificationMode==='code'"
                >
                  <div class="d-flex ai-c">
                    <el-input
                      v-model.trim="form.code"
                      placeholder="请输入验证码"
                      tabindex="3"
                      @keydown.enter.native="handleLogin"
                    />
                    <img
                      :src="captchaSrc"
                      style="margin-left: 10px;height: 40px;"
                      @click="getCaptcha"
                    >
                  </div>
                </el-form-item>
                <div
                  class="huak-box"
                  v-if="verificationMode==='slider'"
                >
                  <Verify
                    mode="nomask"
                    @success="success"
                    captcha-type="blockPuzzle"
                    :img-size="{ width: '358px', height: '140px' }"
                    ref="verify"
                  />
                </div>
              </template>
              <el-button
                :loading="loading"
                class="login-button"
                type="primary"
                :disabled="!useSms && verificationMode==='slider' && !code"
                @click="handleLogin"
              >
                登 录
              </el-button>
            </el-form>
            <div class="flex-ai-c m-t-s p-h-s f-14 jc-sb">
              <div
                class="flex-1"
                v-if="appList"
              >
                <div class="flex-0 flex-ai-c">
                  <el-popover
                    placement="bottom"
                    width="240"
                    trigger="click"
                  >
                    <div class="m-b-mini ta-c">
                      扫描二维码下载
                    </div>
                    <div
                      class="flex-ai-c jc-c"
                      v-for="app in appList"
                      :key="app.id"
                    >
                      <div class="d-flex-c jc-c ai-c">
                        <img
                          :src="'data:image/png;base64,' + app.appPath"
                          style="width: 200px;"
                        >
                        <span class="m-t-mini">{{ app.appName }}</span>
                      </div>
                    </div>
                    <span
                      class="c-blue c-pointer mobile flex-0 flex-ai-c"
                      slot="reference"
                    ><BKSvgIcon
                      icon-class="svg-sys-app"
                      class="f-20 c-blue m-r-tiny"
                    />
                      应用下载</span>
                  </el-popover>
                </div>
              </div>
              <div
                class="flex-0 flex-ai-c"
                v-if="hasSms"
              >
                其他方式登录：<span
                  class="c-blue c-pointer mobile"
                  @click="useSms=!useSms"
                ><i
                  class="el-icon-mobile m-r-tiny"
                  :class="[useSms ? 'el-icon-user' : 'el-icon-mobile']"
                />{{ useSms ? passwordTitle : smsTitle }}</span>
              </div>
              <div
                class="flex-0 d-flex"
                v-if="hasRegister"
              >
                还没有账号？<span class="c-blue c-pointer has-hover">立即注册</span>
              </div>
              <div v-else />
              <el-popover
                v-if="canForgetPassword"
                placement="bottom"
                title="找回密码"
                width="340"
                trigger="click"
                content="请致电：010-63204447联系管理员找回密码。"
              >
                <div
                  class="flex-0 c-pointer has-hover"
                  slot="reference"
                >
                  忘记密码
                </div>
              </el-popover>
            </div>
          </div>
          <div
            v-else
            style="min-height: 457px;"
            class="d-flex-c jc-c"
          >
            <div
              class="title-area"
              v-if="currentScanCodeStatus!==1"
            >
              扫码安全登录
            </div>
            <div class="d-flex jc-c p-v-s position-relative">
              <el-image :src="scanCodeImage" />
              <div
                class="scan-code-image-info"
                :class="`status-${currentScanCodeStatus}`"
                v-if="[-1, 1].includes(currentScanCodeStatus)"
              >
                <div
                  class="d-flex-c ai-c c-white c-pointer"
                  v-if="currentScanCodeStatus===-1"
                  @click="getScanCode"
                >
                  <i class="el-icon-refresh f-44" />
                  <span class="m-t-mini f-16">刷新二维码</span>
                </div>
              </div>
            </div>
            <div
              class="c-white m-t-mini d-flex-c ai-c"
              v-if="currentScanCodeStatus===1"
            >
              <span class="f-28 f-w7 m-b-s">扫码成功</span>
              <span class="f-16">请在移动端确认登录</span>
            </div>
            <div
              class="c-white m-t-mini d-flex-c ai-c"
              v-else-if="currentScanCodeStatus===0"
            >
              <span class="f-16">请使用移动端 App 应用扫描二维码</span>
            </div>
            <div
              class="d-flex jc-c f-14"
              v-if="hasRegister"
            >
              还没有账号？<span class="c-blue c-pointer has-hover">立即注册</span>
            </div>
          </div>
        </div>
      </div>
    </div>
    <div
      class="footer-banner"
      v-if="currentThemeId === 'gs' && features.length"
    >
      <span
        v-for="(f, i) in features"
        :key="i"
      >{{ f }}</span>
    </div>
    <Settings
      ref="settings"
      :themes="themeList"
      :current="currentThemeId"
      @change="handleThemeChange"
    />
    <div
      class="setting-icon"
      @click="$refs.settings.show()"
    >
      <i class="el-icon-setting" />
    </div>
  </div>
</template>

<script>
import { mapActions } from 'vuex'
import { authentication, dictionarySchema } from '@/configs'
import { JSEncrypt } from 'jsencrypt'
import request from '@/utils/request'
import Swiper from './components/swiper.vue'
import Settings from './components/settings.vue'

// 密钥对生成 http://web.chacuo.net/netrsakeypair

const publicKey = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCk+8ad8AvD2LOH7uQhksZTpvY95eoBHBS3gKT6eYBuSR4FgFfCvPJzHO1mi09OGx59L1TRBxtpFwvP5b6YijMNL/BJfHhgqbJT8kdWlaYOt3WchCQkcqOHwNGJaU1mUNJj0eK+WsFBxOHsmy/cXL1waIeyPfDiLfbp67iyRqCl1wIDAQAB'

function encrypt (txt) {
  const encryptor = new JSEncrypt()
  encryptor.setPublicKey(publicKey)
  return encryptor.encrypt(txt)
}

export default {
  name: 'Login',
  components: {
    Verify: () => import('./verifition/Verify.vue'),
    Swiper,
    Settings
  },
  data () {
    return {
      inited: false,
      authentication,
      verificationMode: 'slider',
      form: {
        username: '',
        password: '',
        code: '',
        mobile: '',
        smsCode: '',
        bifactorCode: ''
      },
      loading: false,
      redirect: null,
      captchaSrc: '',
      code: '',
      usePassword: true,
      passwordType: 'password',
      hasRegister: false,
      canChangeSignWay: false,
      canChangePasswordType: false,
      canForgetPassword: false,
      themeList: [],
      currentThemeId: localStorage.getItem(dictionarySchema + '_loginTheme') || 'kj',
      currentTheme: {},
      swiperList: [],
      features: [],
      hasSms: false,
      useSms: false,
      passwordTitle: '用户密码登录',
      smsTitle: '',
      appList: null,
      scanCodeImage: '',
      currentScanCodeStatus: -2,
      bifactorType: '',
      countDown: 60,
      sendCodeButtonDisabled: false,
      sendCodeButtonText: '获取验证码'
    }
  },
  computed: {
    rules () {
      if (this.useSms) {
        return {
          mobile: [
            { required: true, message: '手机号码不能为空' }
          ],
          smsCode: [
            { required: true, message: '验证码不能为空' }
          ]
        }
      }
      const model = {
        username: [
          { required: true, message: '用户名不能为空' }
        ],
        password: [
          { required: true, message: '密码不能为空' }
        ]
      }
      if (this.verificationMode === 'code') {
        model.code = [
          { required: true, message: '验证码不能为空' }
        ]
      }
      if (this.bifactorType) {
        model.bifactorCode = [
          { required: true, message: '验证码不能为空' }
        ]
      }
      return model
    }
  },
  watch: {
    $route: {
      handler (route) {
        this.redirect = route?.query?.redirect || '/'
      },
      immediate: true
    },
    usePassword (v) {
      if (!v) {
        this.getScanCode()
      }
    }
  },
  async created () {
    if (!authentication) {
      await this.login(this.form)
      await this.$router.push(this.handleRoute())
      return
    }
    this.getLoginConfig()
  },
  beforeDestroy () {
    this.timer && clearInterval(this.timer)
  },
  methods: {
    ...mapActions({
      login: 'user/login'
    }),
    async getBifactorCode () {
      if (!this.form.username) {
        return this.$message.warning('请先输入用户名')
      }
      this.sendCodeButtonDisabled = true
      const data = await request.post(this.bifactorType === 'mail' ? '/email/code' : '/sms/alibaba', { username: this.form.username })
      this.bifactorUid = this.bifactorType === 'mail' ? data.emailuid : data.smsuid
      localStorage.setItem('bifactorUid', this.bifactorUid)
      this.$message.success(data.msg || '发送验证码成功！')
      this.startCountDown()
    },
    checkCountDown () {
      const countDown = localStorage.getItem('countDown')
      if (countDown) {
        if (this.bifactorType) {
          this.bifactorUid = localStorage.getItem('bifactorUid')
        }
        this.countDown = countDown
        this.sendCodeButtonDisabled = true
        this.sendCodeButtonText = `${this.countDown--} 秒`
        this.startCountDown()
      }
    },
    startCountDown () {
      this.timer = setInterval(() => {
        console.log('setInterval')
        if (this.countDown < 1) {
          clearInterval(this.timer)
          this.sendCodeButtonText = this.$options.data().sendCodeButtonText
          this.countDown = this.$options.data().countDown
          this.sendCodeButtonDisabled = false
          localStorage.removeItem('countDown')
          return
        }
        this.sendCodeButtonText = `${this.countDown--} 秒`
        localStorage.setItem('countDown', this.countDown)
      }, 1000)
    },
    async sendSms () {
      if (!this.form.mobile) {
        return this.$message.warning('请先输入手机号')
      }
      this.sendCodeButtonDisabled = true
      await request.post('/sms/alibaba', { mobile: this.form.mobile })
      this.$message.success('发送验证码成功！')
      this.startCountDown()
    },
    async getLoginConfig () {
      const res = await request.get('/user/getLoginTheme')
      localStorage.setItem(dictionarySchema + '_ssoSettings', JSON.stringify({ casSso: res.casSso, watfSso: res.watfSso, casLayoutUrl: res.casLayoutUrl }))
      if (res.casSso) {
        const { token } = await request.post('/caslogin')
        if (token) {
          this.$store.commit('user/setToken', token)
        }
        if (res.watfSso) {
          const ssoRes = await request.post('/ssocas/login')
          if (!ssoRes.isLogin) {
            location.href = ssoRes.authUrl
            return
          }
        }
        // await this.$router.push(this.handleRoute())
        await this.$router.push('/hbsw')
        return
      } else if (res.watfSso) {
        this.$router.replace('/sso-login')
        return
      }
      this.verificationMode = res.captchaType === 'huakuai' ? 'slider' : 'code'
      this.bifactorType = res.validation
      if (this.bifactorType) {
        this.checkCountDown()
      }
      this.inited = true
      if (this.verificationMode === 'code') {
        this.getCaptcha()
      }
      if (!res.loginTheme) return
      res.loginTheme.sort((a, b) => {
        if (!a || !b) return 1
        return a.THEME_ORD - b.THEME_ORD
      })
      this.themeList = res.loginTheme.filter(t => t.THEME_STATUS !== '0')
      if (res.loginConfig[0]) {
        const lc = res.loginConfig[0]
        localStorage.setItem(dictionarySchema + '_loginSettings', JSON.stringify(lc))
        if (!this.currentThemeId) {
          this.currentThemeId = lc.LOGIN_THEME
        }
        this.appList = res.isapp ? res.appConfig : null
        this.hasRegister = lc.IS_REGISTER === '1'
        this.canChangeSignWay = lc.IS_QRCODE === '1'
        this.canChangePasswordType = lc.IS_VISUAL === '1'
        this.canForgetPassword = lc.IS_FORGOT === '1'
        this.hasSms = lc.IS_SMS === '1'
        if (!this.bifactorType && this.hasSms) {
          this.checkCountDown()
        }
        this.smsTitle = lc.SMS_DESC || '短信验证码登录'
      }
      this.currentTheme = this.themeList.find(t => t.THEME_ID === this.currentThemeId)
      this.loginSwiperImages = res.loginThemeFj
      this.getSwiperList()
    },
    getSwiperList () {
      this.swiperList = this.loginSwiperImages
        .filter(item => item.THEME_ID === this.currentThemeId)
        .map(item => ({ bg: item.PIC_PATH, dotBg: item.PIC_PATH_SLT }))
      if (this.currentThemeId === 'gs') {
        this.features = this.currentTheme.THEME_DESC.split(',')
      }
    },
    handleThemeChange (theme) {
      this.currentTheme = theme
      this.currentThemeId = theme.THEME_ID
      localStorage.setItem(dictionarySchema + '_loginTheme', this.currentThemeId)
      this.getSwiperList()
    },
    success (params) {
      this.code = params.captchaVerification
    },
    handleRoute () {
      return this.redirect === '/404' || this.redirect === '/403'
        ? '/'
        : this.redirect
    },
    togglePasswordType () {
      if (this.passwordType === 'password') {
        this.passwordType = ''
      } else {
        this.passwordType = 'password'
      }
      this.$nextTick(() => {
        this.$refs.password.focus()
      })
    },
    handleLogin () {
      this.$refs.form.validate((valid) => {
        if (valid) {
          this.confirmLogin()
        } else {
          return false
        }
      })
    },
    async confirmLogin () {
      try {
        this.loading = true
        if (this.useSms) {
          const model = {
            mobile: this.form.mobile,
            smsCode: this.form.smsCode
          }
          const { token } = await request.post('/smslogin', model)
          if (token) {
            this.$store.commit('user/setToken', token)
          }
        } else {
          const model = {
            username: this.form.username,
            password: encrypt(this.form.password)
          }
          if (this.verificationMode === 'code') {
            model.code = this.form.code
            model.uuid = this.uuid
          } else {
            model.code = this.code
          }
          if (this.bifactorType) {
            model[this.bifactorType === 'mail' ? 'emailuid' : 'smsuid'] = this.bifactorUid
            model[this.bifactorType === 'mail' ? 'emailCode' : 'smsCode'] = this.form.bifactorCode
          }
          await this.login(model)
        }
        localStorage.removeItem('countDown')
        await this.$router.push(this.handleRoute())
      } catch {
        if (this.useSms) return
        if (this.verificationMode === 'code') {
          this.getCaptcha()
        } else {
          this.code = ''
          this.$refs.verify.refresh()
        }
      } finally {
        this.loading = false
      }
    },
    async getCaptcha () {
      const data = await request.get('/captchaImage')
      this.captchaSrc = 'data:image/jpg;base64,' + data.img
      this.uuid = data.uuid
    },
    async getScanCode () {
      if (this.currentScanCodeStatus === 0) {
        if (!this.checkQRCodeStatus) {
          this.checkScanCodeState()
        }
        return
      }
      const data = await request.get('/createQrCodeImg')
      this.scanCodeImage = 'data:image/png;base64,' + data.QrCode
      this.scanCodeUuid = data.uuid
      this.currentScanCodeStatus = 0
      this.checkScanCodeState()
    },
    async checkScanCodeState () {
      this.checkQRCodeStatus = true
      const data = await request.get('/getQrCodeStatus', {
        uuid: this.scanCodeUuid,
        currentStatus: this.currentScanCodeStatus
      })
      this.checkQRCodeStatus = false
      if (this.usePassword) return
      this.currentScanCodeStatus = data.status
      if ([0, 1].includes(this.currentScanCodeStatus)) {
        this.checkScanCodeState()
      } else if (this.currentScanCodeStatus === 2) {
        if (data.access_token) {
          this.$store.commit('user/setToken', data.access_token)
          await this.$router.push(this.handleRoute())
        } else {
          this.$message.error('未返回 access_token')
        }
      }
    }
  }
}
</script>

<style lang="scss" scoped>
@import "./styles/base";
@import "./styles/jy";
@import "./styles/kj";
@import "./styles/lb";
@import "./styles/gs";

.scan-code-image-info {
  position: absolute;
  z-index: 1;
  top: 20px;
  left: 0;
  right: 0;
  bottom: 20px;
  display: flex;
  align-items: center;
  justify-content: center;

  &.status--1 {
    background: rgba($color: #000, $alpha: 0.75);
  }

  &.status-1 {
    background: rgba($color: #fff, $alpha: 0.5);
  }
}
</style>
